﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.VersionControl.Client;

namespace MergeTool.ClassLib.Common
{
    /// <summary>
    /// Tiny helper class for using temporary workspaces.
    /// </summary>
    /// <see cref="http://www.vlaquest.com"/>
    public class TfsTempWorkspace : IDisposable
    {
        private Workspace _workspace;
        private VersionControlServer _vcs;
        private string tempWorkspacePath;
        /// <summary>
        /// Creates a workspace. If a workspace with the same name exists, it will be deleted and recreated!
        /// </summary>
        public TfsTempWorkspace(VersionControlServer vcs, string workspaceName, string userName, string WorkspacePath)
        {
            _vcs = vcs;
            _workspace = _vcs.QueryWorkspaces(workspaceName, userName, Environment.MachineName).FirstOrDefault();
            this.tempWorkspacePath = WorkspacePath;
            if (_workspace != null)
            {
                Dispose();
            }
            _workspace = _vcs.CreateWorkspace(workspaceName);
            CleanDirectory();
        }

        /// <summary>
        /// Give access to many properties of the workspace
        /// </summary>
        public Workspace Workspace
        {
            get
            {
                return _workspace;
            }
        }

        /// <summary>
        /// Adds a mapping to the workspace.
        /// The local folders and files will be created under the user TEMP directory.
        /// </summary>
        /// <param name="serverPath">Full path on server, starting from root, ex: $/MyTP/MyFolder</param>
        /// <param name="localRelativePath">A relative path inside the local workspace folder structure</param>
        /// <returns>The local full path</returns>
        public string Map(string serverPath, string localRelativePath)
        {
            string localPath = Path.Combine(tempWorkspacePath, _workspace.Name, localRelativePath);
            _workspace.Map(serverPath, localPath);
            return localPath;
        }

        public void CleanDirectory()
        {
            string rootPath = Path.Combine(tempWorkspacePath, _workspace.Name);
            if (Directory.Exists(rootPath))
            {
                DeleteDirectory(rootPath);
            }
        }

        /// <summary>
        /// All local files are deleted, and the workspace is then removed from the server
        /// </summary>
        public void Dispose()
        {
            CleanDirectory();
            _workspace.Delete();
        }

        public static void DeleteDirectory(string targetDir)
        {
            string[] files = Directory.GetFiles(targetDir);
            string[] dirs = Directory.GetDirectories(targetDir);

            foreach (string file in files)
            {
                File.SetAttributes(file, FileAttributes.Normal);
                File.Delete(file);
            }

            foreach (string dir in dirs)
            {
                DeleteDirectory(dir);
            }

            int retryCount = 0;
            while (true)
            {
                try
                {
                    Directory.Delete(targetDir, false);
                    break;
                }
                catch (IOException ex)
                {
                    retryCount++;
                    
                    if (retryCount >= 3)
                    {
                        throw new Exception("Error occured during removal of:" + targetDir);
                    }
                    Thread.Sleep(100);
                }
            }

            
        }
    }
}
